package jcurses.widgets;

import jcurses.event.ActionEvent;
import jcurses.event.ActionListener;
import jcurses.event.ActionListenerManager;
import jcurses.system.CharColor;
import jcurses.system.InputChar;
import jcurses.system.Toolkit;
import jcurses.util.Rectangle;

/**
 * This class implements a buttton-widget. Such button has a label and is
 * 'clicked' by user typing a special character (default 'enter'). If it is
 * 'clicked', it generates an <code>ActionEvent</code>, that is delegetated to
 * registered listeners.
 */
public class Button extends Widget implements IShortCutable {

	private ActionListenerManager _listenerManager = new ActionListenerManager();

	private FocusData focus = new FocusData();

	private static CharColor __buttonDefaultColors = new CharColor(
			CharColor.WHITE, CharColor.BLACK);

	private String _label = null;

	private static CharColor __focusedButtonDefaultColors = new CharColor(
			CharColor.BLUE, CharColor.WHITE, CharColor.REVERSE);

	private CharColor _focusedButtonColors = getFocusedButtonDefaultColors();

	private static CharColor __shortCutDefaultColors = new CharColor(
			CharColor.WHITE, CharColor.RED);

	private CharColor _shortCutColors = getShortCutDefaultColors();
	private static InputChar __actionChar = new InputChar('\n');

	// Shortcut
	private InputChar _shortCut = null;

	/**
	 * The constructor
	 * 
	 * @param button
	 *            's label
	 */
	public Button(String label) {
		_label = label;
	}

	/**
	 * Adds a listener to the button.
	 * 
	 * @param listener
	 *            listener to add
	 */
	public void addListener(ActionListener listener) {
		_listenerManager.addListener(listener);
	}

	@Override
	public CharColor getDefaultColors() {
		return __buttonDefaultColors;
	}

	@Override
	public void getFocus() {
		this.focus.focus = true;
		changeColors();
	}

	/**
	 * @return button's colors, if it is focused
	 */
	public CharColor getFocusedButtonColors() {
		return _focusedButtonColors;
	}

	/**
	 * @return button's label
	 */
	public String getLabel() {
		return _label;
	}

	@Override
	public InputChar getShortCut() {
		return _shortCut;
	}

	/**
	 * @return colors button's shortcut char's colors
	 */
	public CharColor getShortCutColors() {
		return _shortCutColors;
	}

	@Override
	public boolean handleInput(InputChar ch) {
		if ((ch.equals(__actionChar))
				|| ((getShortCut() != null) && (getShortCut().equals(ch)))) {
			doAction();
			return true;
		}

		return false;
	}

	@Override
	public boolean hasFocus() {
		return this.focus.focus;
	}

	@Override
	public boolean isFocusable() {
		return this.focus.focusable;
	}

	@Override
	public void lostFocus() {
		this.focus.focus = false;
		changeColors();
	}

	/**
	 * Removes a listener from the button.
	 * 
	 * @param listener
	 *            listener to remove
	 */
	public void removeListener(ActionListener listener) {
		_listenerManager.removeListener(listener);
	}

	@Override
	public void setFocus(boolean value) {
		if (value) {
			getFocus();
		} else {
			lostFocus();
		}
	}

	@Override
	public void setFocusable(boolean focusable) {
		this.focus.focusable = focusable;
	}

	/**
	 * Sets button's colors in focused state
	 * 
	 * @param colors
	 *            button's colors, if it is focused
	 */
	public void setFocusedButtonColors(CharColor colors) {
		_focusedButtonColors = colors;
	}

	/**
	 * Sets button's label
	 * 
	 * @param label
	 *            buttton's label
	 */
	public void setLabel(String label) {
		_label = label;

	}

	/**
	 * Set's button's shortcut char. If this shortcut is typed, than the button
	 * will handle the char, as described by <code>Widget</code>, and generate
	 * an Event as whether the button would be 'clicked'.
	 */
	@Override
	public void setShortCut(char c) {
		_shortCut = new InputChar(c);
	}

	/**
	 * Sets button's shortcut char's colors. If the button has a shortcut char
	 * and this char is contained by the label, than the char within the label
	 * will be painted in different colors, set by this method
	 * 
	 * @param colors
	 *            button's shortcut char's colors
	 */
	public void setShortCutColors(CharColor colors) {
		_shortCutColors = colors;
	}

	private void changeColors() {
		CharColor colors = hasFocus() ? getFocusedButtonColors() : getColors();
		Toolkit.changeColors(getRectangle(), colors);
	}

	private void doAction() {
		_listenerManager.handleEvent(new ActionEvent(this));
	}

	private void drawShortCutIfNeeded() {
		InputChar shortCut = getShortCut();
		if (shortCut != null) {
			String c = shortCut.toString();
			if (_label != null) {
				int index = _label.toLowerCase().indexOf(c.toLowerCase());
				if (index != -1) {
					String c1 = _label.substring(index, index + 1);
					Toolkit.printString(c1, getAbsoluteX() + index + 2,
							getAbsoluteY(), getShortCutColors());
				}
			}
		}
	}

	private CharColor getFocusedButtonDefaultColors() {
		return __focusedButtonDefaultColors;
	}

	private CharColor getShortCutDefaultColors() {
		return __shortCutDefaultColors;
	}

	@Override
	protected void doPaint() {
		Rectangle rect = getRectangle();
		String text = "< " + _label + " >";
		CharColor colors = hasFocus() ? getFocusedButtonColors() : getColors();
		Toolkit.printString(text, rect, colors);
		if (!hasFocus()) {
			drawShortCutIfNeeded();
		}
	}

	@Override
	protected void doRepaint() {
		doPaint();
	}

	@Override
	protected Rectangle getPreferredSize() {
		return new Rectangle(_label.length() + 4, 1);
	}

}
